﻿using CommonBase;
using CommonClass;
using EnvControlLib;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Regions;
using SurveillanceLib;
using SurveillancePro.Base.DataEnum;
using SurveillancePro.Base.ViewModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Input;
using ToolkitMgtModule.Models;

namespace ToolkitMgtModule.ViewModels
{
    /// <summary>
    /// 远程录像回放
    /// </summary>
    public class ViewModel_PlayBack : WorkspaceViewModel
    {
        #region Private Fields

        private DelegateCommand _cmdSearchList, _cmdDownloadFile, _cmdConvertFile, _cmdPlayVideo;
        private List<FileDetailModel> _selectedFileDetailList; // 所选文件列表

        private readonly IEventAggregator _eventAggregator;

        #endregion

        #region Constructor

        public ViewModel_PlayBack(IRegionManager regionManager, IEventAggregator eventAggregator)
        {
            if (regionManager == null || eventAggregator == null)
                return;

            base.BaseRegionManager = regionManager;
            base.ViewName = SurveillancePro.Base.Common.ViewNames.ToolkitMgtModule_PlayBack;
            base.HeaderTitle = "录像回放";
            base.HeaderImageSource = string.Format(ConstantString.IMAGE_URL, "Question");
            base.IsShowCloseButton = Visibility.Visible;
            this._eventAggregator = eventAggregator;

            FileFilter = new FileFilterModel();
            SurveillancePro.Base.Manager.EventManagers.RefreshTreeEvent +=
                FileFilter.LoadDeviceTreeData; // 刷新设备树
            SurveillancePro.Base.Manager.EventManagers.RefreshTreeWithLoginEvent +=
                FileFilter.LoadDeviceTreeData; // 刷新设备树【设备登录与否】

            // 打开所有工作区 Tab
            _manageDownloadFile(_selectedFileDetailList);
            //_manageConvertFile(_selectedFileDetailList);
            _managePlayVideo(SelectedFile);
        }

        #endregion

        #region Base Class Overrides

        protected override void OnDispose()
        {
            _dispose();
        }

        #endregion

        #region Public Properties

        private ObservableCollection<WorkspaceViewModel> _workspaces;
        /// <summary>
        /// Returns the collection of available workspaces to display.
        /// A 'workspace' is a ViewModel that can request to be closed.
        /// </summary>
        public ObservableCollection<WorkspaceViewModel> Workspaces
        {
            get
            {
                if (_workspaces == null)
                {
                    _workspaces = new ObservableCollection<WorkspaceViewModel>();
                    _workspaces.CollectionChanged += this.OnWorkspacesChanged;
                }
                return _workspaces;
            }
        }

        /// <summary>
        /// 文件过滤
        /// </summary>
        public FileFilterModel FileFilter { get; set; }

        /// <summary>
        /// 文件详情列表
        /// </summary>
        public ObservableCollection<FileDetailModel> FileDetailList { get; set; }

        private FileDetailModel _selectedFile;
        /// <summary>
        /// 列表所选 File
        /// </summary>
        public FileDetailModel SelectedFile
        {
            get { return _selectedFile; }
            set
            {
                if (value == _selectedFile) return;
                _selectedFile = value;
                base.OnPropertyChanged("SelectedFile");
            }
        }

        private WorkStateEnum _workState;
        /// <summary>
        /// 状态
        /// </summary>
        public WorkStateEnum WorkingState
        {
            get { return _workState; }
            set
            {
                if (value == _workState) return;
                _workState = value;

                base.OnPropertyChanged("WorkingState");
                SurveillancePro.Base.Reflector.WorkingStateProperty.OnWorkingStatePropertyChanged(this); // 更新界面
            }
        }

        /// <summary>
        /// 是否显示 进度条
        /// </summary>
        public bool Indicator_IsBusy { get; set; }

        private bool? _isSelectAll = false; // 初值：表示不“全选”
        /// <summary>
        /// CheckBox 是否全选
        /// <para>三态</para>
        /// </summary>
        public bool? IsSelectAll
        {
            get
            {
                return _isSelectAll;
            }
            set
            {
                _isSelectAll = value;
                base.OnPropertyChanged("IsSelectAll");


                if (FileDetailList != null)
                {
                    foreach (FileDetailModel file in FileDetailList)
                    {
                        if (value.HasValue)
                            file.IsSelected = value.Value;
                    }
                }
            }
        }


        [Display(GroupName = "DelegateCommand")]
        public DelegateCommand Cmd_SearchList
        {
            get
            {
                if (_cmdSearchList == null)
                {
                    _cmdSearchList = new DelegateCommand(_searchItemList, _canSearchItemList);
                }
                return _cmdSearchList;
            }
        }

        [Display(GroupName = "DelegateCommand")]
        public DelegateCommand Cmd_DownloadFile
        {
            get
            {
                if (_cmdDownloadFile == null)
                {
                    _cmdDownloadFile = new DelegateCommand(_downloadFile, _canDownloadFile);
                }
                return _cmdDownloadFile;
            }
        }

        [Display(GroupName = "DelegateCommand")]
        public DelegateCommand Cmd_ConvertFile
        {
            get
            {
                if (_cmdConvertFile == null)
                {
                    _cmdConvertFile = new DelegateCommand(_convertFile, _canConvertFile);
                }
                return _cmdConvertFile;
            }
        }

        [Display(GroupName = "DelegateCommand")]
        public DelegateCommand Cmd_PlayVideo
        {
            get
            {
                if (_cmdPlayVideo == null)
                {
                    _cmdPlayVideo = new DelegateCommand(_playVideo, _canPlayVideo);
                }
                return _cmdPlayVideo;
            }
        }

        /// <summary>
        /// 列表选择时
        /// </summary>
        public ICommand Cmd_DataGridSelect
        {
            get
            {
                return new DelegateCommand(() =>
                {
                    ViewModel_PlayBack vm = (ViewModel_PlayBack)this;

                    //When another tab item is selected, data context of this tab item 
                    //becomes null, also this event will be raised, therefore we need to 
                    //add "if" to protect againt exception.
                    if (vm != null)
                        vm._selectItem();
                });
            }
        }

        /// <summary>
        /// 双击列表时
        /// </summary>
        public ICommand Cmd_DataGridDoubleClick
        {
            get
            {
                return new DelegateCommand(() =>
                {
                    ViewModel_PlayBack vm = (ViewModel_PlayBack)this;

                    //When another tab item is selected, data context of this tab item 
                    //becomes null, also this event will be raised, therefore we need to 
                    //add "if" to protect againt exception.
                    if (vm != null)
                        vm.Cmd_PlayVideo.Execute();
                });
            }
        }

        /// <summary>
        /// 列表单个项目选择时
        /// </summary>
        public ICommand Cmd_DataGridClickCheckBox
        {
            get
            {
                return new DelegateCommand(() =>
                {
                    IsSelectAll = Utilities.SetSelectAllCheckBoxState(FileDetailList);
                });
            }
        }

        #endregion

        #region Event Handling Methods

        void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (FileDetailModel file in e.NewItems)
                    file.PropertyChanged += this.OnFileDetailModelPopertyChanged;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (FileDetailModel file in e.OldItems)
                    file.PropertyChanged -= this.OnFileDetailModelPopertyChanged;
        }

        void OnFileDetailModelPopertyChanged(object sender, PropertyChangedEventArgs e)
        {
            // Blank for now
        }

        void OnWorkspacesChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.NewItems)
                    workspace.RequestClose += this.OnWorkspaceRequestClose;

            if (e.OldItems != null && e.OldItems.Count != 0)
                foreach (WorkspaceViewModel workspace in e.OldItems)
                    workspace.RequestClose -= this.OnWorkspaceRequestClose;
        }

        void OnWorkspaceRequestClose(object sender, EventArgs e)
        {
            WorkspaceViewModel workspace = sender as WorkspaceViewModel;

            workspace.Dispose();
            this.Workspaces.Remove(workspace);
        }

        #endregion

        #region Private Methods

        #region DelegateCommand

        private bool _canSearchItemList()
        {
            return true;
        }

        private bool _canDownloadFile()
        {
            return (WorkingState == WorkStateEnum.ItemSelected);
        }

        private bool _canConvertFile()
        {
            return (WorkingState == WorkStateEnum.ItemSelected);
        }

        private bool _canPlayVideo()
        {
            return (WorkingState == WorkStateEnum.ItemSelected);
        }


        /// <summary>
        /// 选择列表
        /// </summary>
        private void _selectItem()
        {
            if (SelectedFile == null || FileDetailList.Count == 0) return;
            WorkingState = WorkStateEnum.ItemSelected;
        }

        /// <summary>
        /// 查询
        /// </summary>
        private void _searchItemList()
        {
            try
            {
                _changeIndicatorState(true);
                IsSelectAll = false; // 不全选

                if (FileDetailList != null)
                    FileDetailList.Clear(); // 清空列表

                if (FileFilter.IsValid != 0) // 存在错误
                {
                    AutoCloseNoticeWindow.Show(FileFilter.Error, true);
                    //AutoCloseNoticeWindow.Show(string.Format("系统中发现{0}个错误，请检查页面！", FileFilter.IsValid), true);
                    _changeIndicatorState(false);
                    return;
                }
                else if (FileFilter.Combo_SearchDriverText != null &&
                    FileFilter.Combo_SearchDriverText.Arg != null &&
                    FileFilter.Combo_SearchDriverText.Arg is TagModel &&
                    (FileFilter.Combo_SearchDriverText.Arg as TagModel).Driver_Instance != null &&
                    !string.IsNullOrWhiteSpace((FileFilter.Combo_SearchDriverText.Arg as TagModel).Driver_LoginID))
                {
                    DateTime startDateTime = FileFilter.Date_SearchStartDate.Value.Add(
                        FileFilter.Time_SearchStartTime.Value.TimeOfDay); // 开始日期时间
                    DateTime endDateTime = FileFilter.Date_SearchEndDate.Value.Add(
                        FileFilter.Time_SearchEndTime.Value.TimeOfDay); // 结束日期时间

                    NetRecordFileInfoStruct[] nriFileInfo = new NetRecordFileInfoStruct[SurveillanceUtilities.FILES_MAXCOUNT];
                    int outFileCount = 0;
                    TagModel driverTag = FileFilter.Combo_SearchDriverText.Arg as TagModel;

                    bool resultQueryRecordFile = driverTag.Driver_Instance.QueryRecordFile(
                        driverTag.Driver_LoginID, FileFilter.Combo_SearchDriverChannel,
                        FileFilter.Combo_SearchRecordFileType.ToString(),
                        startDateTime, endDateTime, null, ref nriFileInfo,
                        SurveillanceUtilities.FILES_MAXCOUNT * Marshal.SizeOf(typeof(NetRecordFileInfoStruct)),
                        out outFileCount, 5000, false); // 查询录像文件

                    if (resultQueryRecordFile) // 查询成功
                    {
                        if (outFileCount == 0)
                        {
                            AutoCloseNoticeWindow.Show("未查询到录像文件！", false);
                            _changeIndicatorState(false);
                            return;
                        }
                        else // 加载文件详情列表
                        {
                            FileDetailModel[] files = _loadAll(nriFileInfo, outFileCount);
                            _updateLayout(_loadFileList(files)); // 加载全部，并更新界面
                        }
                    }
                    else
                    {
#if DEBUG
                        Debug.WriteLine("内部查询录像文件异常！");
#endif
                        MessageBox.Show("查询异常！", ConstantString.MSG_COMPANY);
                    }
                }
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }

            _changeIndicatorState(false);
        }

        /// <summary>
        /// 文件下载
        /// </summary>
        private void _downloadFile()
        {
            try
            {
                if (FileDetailList != null && FileDetailList.Count > 0)
                {
                    _selectedFileDetailList = FileDetailList.Where(c => c.IsSelected).ToList(); // 获得所选文件列表

                    if (_selectedFileDetailList.Count <= 0)
                    {
                        AutoCloseNoticeWindow.Show("请选择要下载的文件！");
                        return;
                    }
                    else
                        _manageDownloadFile(_selectedFileDetailList);
                }
                else
                    AutoCloseNoticeWindow.Show("请选择要下载的文件！");
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }
        }

        /// <summary>
        /// 文件转换
        /// </summary>
        private void _convertFile()
        {
            try
            {
                if (FileDetailList != null && FileDetailList.Count > 0)
                {
                    _selectedFileDetailList = FileDetailList.Where(c => c.IsSelected).ToList(); // 获得所选文件列表

                    if (_selectedFileDetailList.Count <= 0)
                    {
                        AutoCloseNoticeWindow.Show("请选择要转换的文件！");
                        return;
                    }
                    else
                        _manageConvertFile(_selectedFileDetailList);
                }
                else
                    AutoCloseNoticeWindow.Show("请选择要转换的文件！");
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }
        }

        /// <summary>
        /// 文件播放
        /// </summary>
        private void _playVideo()
        {
            try
            {
                if (SelectedFile != null)
                {
                    _managePlayVideo(SelectedFile);
                }
                else
                    AutoCloseNoticeWindow.Show("请选择要播放的文件！");
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }
        }

        #endregion

        #region 工作区 Helpers

        /// <summary>
        /// Manage Download File
        /// </summary>
        /// <param name="selectedFileList">所选文件列表</param>
        private void _manageDownloadFile(List<FileDetailModel> selectedFileList)
        {
            #region 判断是否有文件正在播放
            ViewModel_PlayVideo vm_PlayVideo = this.Workspaces.FirstOrDefault(vm => vm is ViewModel_PlayVideo)
                as ViewModel_PlayVideo;
            if (vm_PlayVideo != null && vm_PlayVideo.FilePlayBackList != null && 
                vm_PlayVideo.FilePlayBackList.Length > 0 &&
                selectedFileList != null && selectedFileList.Count > 0)
            {
                FileDetailModel oneFile = selectedFileList.FirstOrDefault(); // 所选文件的 IP 与通道号都一样
                foreach (FilePlayBackModel filePlayBack in vm_PlayVideo.FilePlayBackList)
                {
                    if (oneFile.DriverIP == filePlayBack.DriverIP &&
                        oneFile.DriverChannel == filePlayBack.DriverChannel)
                    {
                        AutoCloseNoticeWindow.Show("该通道下有文件正在播放，请先停止后再下载！", true);

                        return;
                    }
                }
            }
            #endregion

            ViewModel_DownloadFile workspace =
                this.Workspaces.FirstOrDefault(vm => vm is ViewModel_DownloadFile)
                as ViewModel_DownloadFile;

            if (workspace == null)
            {
                workspace = new ViewModel_DownloadFile();
                this.Workspaces.Add(workspace);
            }

            if (selectedFileList != null)
                workspace.Add2List(selectedFileList); // 添加到下载列表中
            this._setActiveWorkspace(workspace);
        }

        /// <summary>
        /// Manage Convert File
        /// </summary>
        /// <param name="selectedFileList">所选文件列表</param>
        private void _manageConvertFile(List<FileDetailModel> selectedFileList)
        {
            ViewModel_ConvertFile workspace =
                this.Workspaces.FirstOrDefault(vm => vm is ViewModel_ConvertFile)
                as ViewModel_ConvertFile;

            if (workspace == null)
            {
                workspace = new ViewModel_ConvertFile();
                this.Workspaces.Add(workspace);
            }

            if (selectedFileList != null)
                workspace.Add2List(selectedFileList); // 添加到转换列表中
            this._setActiveWorkspace(workspace);
        }

        /// <summary>
        /// Manage Play Video
        /// </summary>
        /// <param name="selectedFile">所选文件</param>
        private void _managePlayVideo(FileDetailModel selectedFile)
        {
            #region 判断是否有文件正在下载
            ViewModel_DownloadFile vm_DownloadFile = this.Workspaces.FirstOrDefault(vm => vm is ViewModel_DownloadFile)
                as ViewModel_DownloadFile;
            if (vm_DownloadFile != null && vm_DownloadFile.DownloadFileList != null &&
                vm_DownloadFile.DownloadFileList.Count > 0 &&
                selectedFile != null)
            {
                foreach (FileDetailModel fileDownload in vm_DownloadFile.DownloadFileList)
                {
                    if (selectedFile.DriverIP == fileDownload.DriverIP &&
                        selectedFile.DriverChannel == fileDownload.DriverChannel)
                    {
                        AutoCloseNoticeWindow.Show("该通道下有文件正在下载，请先停止后再播放！", true);

                        return;
                    }
                }
            }
            #endregion

            ViewModel_PlayVideo workspace =
                this.Workspaces.FirstOrDefault(vm => vm is ViewModel_PlayVideo)
                as ViewModel_PlayVideo;

            if (workspace == null)
            {
                workspace = new ViewModel_PlayVideo(_eventAggregator);
                this.Workspaces.Add(workspace);
            }

            if (selectedFile != null)
                workspace.PlayVideo(selectedFile); // 播放文件
            this._setActiveWorkspace(workspace);
        }

        #endregion

        /// <summary>
        /// 获取所有 File Detail Model -- 绑定 Model 中的方法与属性
        /// </summary>
        /// <param name="fileList">文件列表</param>
        /// <param name="fileCount">实际文件个数</param>
        /// <returns></returns>
        private FileDetailModel[] _loadAll(NetRecordFileInfoStruct[] fileList, int fileCount)
        {
            if (fileList == null || fileList.Length <= 0)
            {
                _changeIndicatorState(false);
                return null;
            }

            FileDetailModel[] _files = new FileDetailModel[fileCount];
            for (int i = 0; i < fileCount; i++)
            {
                _files[i] = new FileDetailModel(fileList[i])
                {
                    DriverText = FileFilter.Combo_SearchDriverText.Name,
                    DriverIP = (FileFilter.Combo_SearchDriverText.Arg as TagModel).Driver_IP,
                    RecordFileType = FileFilter.Combo_SearchRecordFileType,
                    SelectedDriver = FileFilter.Combo_SearchDriverText.Arg as TagModel,
                };
            }

            return _files;
        }

        /// <summary>
        /// 加载列表，并返回第一行，用于默认选中
        /// </summary>
        /// <param name="files"></param>
        /// <returns></returns>
        private FileDetailModel _loadFileList(FileDetailModel[] files)
        {
            if (files == null)
            {
                _changeIndicatorState(false);
                return null;
            }

            FileDetailList = new ObservableCollection<FileDetailModel>();
            _changeIndicatorState(true);

            foreach (FileDetailModel file in files)
            {
                file.PropertyChanged += this.OnFileDetailModelPopertyChanged;
                FileDetailList.Add(file);
            }
            FileDetailList.CollectionChanged += this.OnCollectionChanged;

            _changeIndicatorState(false);
            return files.FirstOrDefault();
        }

        /// <summary>
        /// 更新界面
        /// </summary>
        /// <param name="model"></param>
        private void _updateLayout(FileDetailModel model)
        {
            SelectedFile = model;
            base.OnPropertyChanged("FileDetailList");

            if (SelectedFile == null)
            {
                WorkingState = WorkStateEnum.NoItemSelected;
            }
            else
            {
                WorkingState = WorkStateEnum.ItemSelected;
            }
        }

        /// <summary>
        /// 修改 进度条 状态
        /// </summary>
        /// <param name="state"></param>
        private void _changeIndicatorState(bool state)
        {
            Indicator_IsBusy = state;
            base.OnPropertyChanged("Indicator_IsBusy");
        }

        /// <summary>
        /// 激活工作区
        /// </summary>
        /// <param name="workspace"></param>
        private void _setActiveWorkspace(WorkspaceViewModel workspace)
        {
#if DEBUG
            Debug.Assert(this.Workspaces.Contains(workspace));
#endif
            ICollectionView collectionView = System.Windows.Data.CollectionViewSource.GetDefaultView(this.Workspaces);
            if (collectionView != null)
                collectionView.MoveCurrentTo(workspace);
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        private void _dispose()
        {
            try
            {
                // 注：若为“单例模式”，则不能进行反注册！
                SurveillancePro.Base.Manager.EventManagers.RefreshTreeEvent -=
                    FileFilter.LoadDeviceTreeData; // 反注册
                SurveillancePro.Base.Manager.EventManagers.RefreshTreeWithLoginEvent -=
                    FileFilter.LoadDeviceTreeData; // 反注册

                if (FileDetailList != null)
                {
                    FileDetailList.Clear();
                    FileDetailList.CollectionChanged -= this.OnCollectionChanged;
                }

                if (Workspaces != null)
                {
                    // 释放 ViewModel_Tabs
                    foreach (WorkspaceViewModel vm in Workspaces)
                        vm.Dispose();

                    Workspaces.Clear();
                    Workspaces.CollectionChanged -= this.OnWorkspacesChanged;
                }
            }
            catch (System.Exception ex)
            {
#if DEBUG
                Debug.WriteLine(ex.Message);
#endif
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// 文件查询
        /// </summary>
        public void SearchItemList()
        {
            _searchItemList(); // 查询列表
        }

        /// <summary>
        /// 文件查询
        /// </summary>
        /// <param name="driverText">设备 IP 地址</param>
        /// <param name="driverChannel">所选通道号</param>
        public void SearchItemList(string driverIP, string driverChannel)
        {
            #region 初值
            FileFilter.Combo_SearchDriverText = null;
            FileFilter.Combo_SearchDriverChannel = -1;
            FileFilter.Date_SearchStartDate = DateTime.Now.Date.AddDays(-1);
            FileFilter.Date_SearchEndDate = DateTime.Now.Date;
            FileFilter.Time_SearchEndTime = FileFilter.Time_SearchStartTime = DateTime.Now;
            #endregion

            // 寻找设备列表
            if (!string.IsNullOrWhiteSpace(driverIP) &&
                FileFilter.Combo_DriverTexts != null && FileFilter.Combo_DriverTexts.Count > 0)
            {
                foreach (ITreeGroup driver in FileFilter.Combo_DriverTexts)
                {
                    if (driver.Arg != null && driver.Arg is TagModel &&
                        (driver.Arg as TagModel).Driver_IP == driverIP)
                    {
                        FileFilter.Combo_SearchDriverText = driver;

                        break;
                    }
                }
            }

            // 寻找通道号列表
            int outSelectedChannel;
            if (FileFilter.Combo_DriverChannels != null && FileFilter.Combo_DriverChannels.Count > 0 &&
                !string.IsNullOrWhiteSpace(driverChannel) && 
                int.TryParse(driverChannel, out outSelectedChannel))
            {
                FileFilter.Combo_SearchDriverChannel = outSelectedChannel;
            }

            _searchItemList(); // 查询列表
        }

        #endregion
    }
}